from PyQt5.QtGui import QIntValidator, QIcon
from PyQt5.QtNetwork import QUdpSocket, QHostAddress
from PyQt5.QtWidgets import (
    QApplication,
    QLabel,
    QHBoxLayout,
    QPushButton,
    QTextEdit,
    QLineEdit,
    QCheckBox,
    QComboBox,
    QWidget,
    QVBoxLayout, QMessageBox
)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
import socket
import random
from PySendForRad.sources_svg import ICON_TITLE


class ClientThread(QThread):
    message_received = pyqtSignal(str)

    def __init__(self, parent=None):
        super(ClientThread, self).__init__(parent)
        self.socket = QUdpSocket()

    def run(self):
        self.socket.readyRead.connect(self.receive_message)

    def receive_message(self):
        while self.socket.hasPendingDatagrams():
            datagram, host, port = self.socket.readDatagram(self.socket.pendingDatagramSize())
            message = datagram.data().decode()
            self.message_received.emit(message)

    def send_message(self, message, host, port):
        self.socket.writeDatagram(message.encode(), QHostAddress(host), port)


def find_unused_port() -> str:
    """
    随机获取一个未被使用的端口号
    @param:
    @return:
    """
    while True:
        port = random.randint(1024, 65535)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = s.connect_ex(('127.0.0.1', port))
        s.close()
        if result != 0:  # 如果端口未被使用
            return f'{result}'


def check_port_availability(host: str, port: int) -> bool:
    """
    检查端口是否可用
    @param host:
    @param port:
    @return:
    """
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        try:
            s.bind((host, port))
        except OSError:
            return True
        return False


class SimpleRadarSimulation(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.host = QLineEdit()
        self.host.setPlaceholderText("目标IP")
        self.port = QLineEdit()
        self.port.setPlaceholderText("目标端口")
        self.specify_local_port: QCheckBox = QCheckBox()
        self.specify_local_port.setText("本地随机端口")
        self.local_port: QLineEdit = QLineEdit()
        self.local_port.setValidator(QIntValidator())
        # 定时发送
        self.is_scheduled_send: QCheckBox = QCheckBox()
        self.is_scheduled_send.setText("定时发送")
        self.scheduled_send_time: QLineEdit = QLineEdit()
        self.scheduled_send_time.setEnabled(False)

        self.protocol_combo = QComboBox(self)
        self.protocol_combo.addItem("UDP")
        self.protocol_combo.addItem("TCP")

        self.send_button = QPushButton(self)
        self.send_button.setText("Send")
        self.send_button.setEnabled(False)
        self.clear_button = QPushButton(self)
        self.clear_button.setText("Clear")
        self.clear_button.setEnabled(False)

        self.send_msg = QTextEdit()
        self.receive_msg_edit = QTextEdit(self)
        self.receive_msg_edit.setReadOnly(True)
        # self.close_button = QPushButton(self)
        # self.close_button.setEnabled(False)

        self.box_h_1: QHBoxLayout = QHBoxLayout()
        self.box_h_2: QHBoxLayout = QHBoxLayout()
        self.box_h_3: QHBoxLayout = QHBoxLayout()

        self.box_s_1: QVBoxLayout = QVBoxLayout()

        self.box_main: QVBoxLayout = QVBoxLayout()

        self.init_ui()
        self.init_ui_layout()
        self.init_connect()

    def init_ui(self):
        """

        @return:
        """
        self.setWindowTitle("Simple Radar Simulation")
        self.setWindowIcon(QIcon("./WindowIcon.svg"))

        self.host.setFixedWidth(100)
        self.port.setFixedWidth(40)
        self.local_port.setFixedWidth(40)
        self.scheduled_send_time.setFixedWidth(40)

    def init_ui_layout(self):
        """
        布局
        @return:
        """
        self.box_h_1.addWidget(QLabel("目标IP："))
        self.box_h_1.addWidget(self.host)
        self.box_h_1.addWidget(QLabel("目标端口："))
        self.box_h_1.addWidget(self.port)

        self.box_h_1.addWidget(QLabel("协议："), alignment=Qt.AlignLeft)
        self.box_h_1.addWidget(self.protocol_combo, alignment=Qt.AlignLeft)

        self.box_h_2.addWidget(self.specify_local_port)
        self.box_h_2.addWidget(QLabel("本地端口："))
        self.box_h_2.addWidget(self.local_port)
        self.box_h_2.addWidget(self.is_scheduled_send, alignment=Qt.AlignLeft)
        self.box_h_2.addWidget(QLabel("定时发送："), alignment=Qt.AlignLeft)
        self.box_h_2.addWidget(self.scheduled_send_time, alignment=Qt.AlignLeft)

        self.box_s_1.addWidget(self.send_msg)
        self.box_s_1.addWidget(self.receive_msg_edit)

        self.box_h_3.addWidget(self.send_button)
        self.box_h_3.addWidget(self.clear_button)

        self.box_main.addLayout(self.box_h_1)
        self.box_main.addLayout(self.box_h_2)
        self.box_main.addLayout(self.box_s_1)
        self.box_main.addLayout(self.box_h_3)

        self.setLayout(self.box_main)

    def init_connect(self):
        """

        @param self:
        @return:
        """
        self.specify_local_port.stateChanged.connect(self.set_local_port_enabled)
        self.local_port.editingFinished.connect(self.check_local_port)

        self.is_scheduled_send.stateChanged.connect(self.set_scheduled_send_enabled)

    def set_local_port_enabled(self, state):
        """
        设置本地端口是否可用
        @param state:
        @return:
        """
        if state == Qt.Checked:
            self.local_port.clear()
            self.local_port.setEnabled(False)
            random_port = find_unused_port()
            print(f"设置随机端口：{random_port}")
            self.local_port.setText(random_port)
            self.send_button.setEnabled(True)
        else:
            self.local_port.clear()
            self.local_port.setEnabled(True)
            self.send_button.setEnabled(True)

    def set_scheduled_send_enabled(self, state):
        """
        设置定时发送
        @return:
        """
        if state == Qt.Checked:
            self.scheduled_send_time.setEnabled(True)
        else:
            self.scheduled_send_time.setEnabled(False)

    def check_local_port(self):
        """
        检查输入端口是否有效
        @return:
        """
        print("检查是否PORT是否有效")
        __inuse = check_port_availability('localhost', int(self.local_port.text()))
        print(__inuse)
        if __inuse:  # 端口可用性
            print("端口可用")
        else:
            print("端口不可用")
            QMessageBox.critical(self, "错误", "端口不可用")
            self.local_port.clear()
            self.local_port.setEnabled(True)


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    # st = StopThreading()
    ui = SimpleRadarSimulation()
    ui.show()
    sys.exit(app.exec_())
